/// Coder: Jose Ricardo Mello Viana - 2008
/// Bugs? e-mail me: zezim.ricardo@gmail.com

#ifndef BONE_H_
#define BONE_H_

#include "typedefs.h"
#include "utils.h"

/// This class implements a bone that will compose a skeleton
class Bone {
public:
   /// Constructor Default
   Bone();
   
   /// Destructor Default
   virtual ~Bone();
   
   /// Get the name of Bone
   /// @return the name of Bone
   inline string getName(){ return name; };
   
   /// Get the direction vector of Bone
   /// @return direction vector of bone
   inline Vector3D getDirection(){ return direction; };
   
   /// Get the length of Bone
   /// @return the length of Bone
   inline double getLength(){ return length; };
   
   /// Get the axis order of Bone
   /// @return the axis order of Bone
   inline string getAxisOrder(){ return axisOrder; };

   /// Get the X axis orientation
   /// @return the X axis orientation
   inline Vector3D getAxisX(){ return axisX; };
   
   /// Get the Y axis orientation
   /// @return the Y axis orientation
   inline Vector3D getAxisY(){ return axisY; };
   
   /// Get the Z axis orientation
   /// @return the Z axis orientation
   inline Vector3D getAxisZ(){ return axisZ; };
   
   /// Get the angles of axis rotations
   /// @return the angles of axis rotations
   inline Vector3D getRotationAxis(){ return rotationAxis; };
   
   /// Get the angles of axis rotations
   /// @return the angles of axis rotations
   inline string getRotAxisOrder(){ return rotAxisOrder; };
   
   /// Set the name of Bone
   /// @param n given new name
   inline void setName(string n){ name = n; };
   
   /// Set the direction of Bone
   /// @param d given new direction
   inline void setDirection(Vector3D d){ direction = d; };
   
   /// Set the length of Bone
   /// @param l given new length
   inline void setLength(double l){ length = l; };
   
   /// Set the axis order of Bone
   /// @param o given new axis order
   inline void setAxisOrder(string o) { axisOrder = o; };
   
   /// Set the X axis orientation
   /// @param x the new X axis orientation
   inline void setAxisX(Vector3D x) { axisX = x; };
   
   /// Set the Y axis orientation
   /// @param y the new Y axis orientation
   inline void setAxisY(Vector3D y) { axisY = y; };
   
   /// Set the Z axis orientation
   /// @param z the new Z axis orientation
   inline void setAxisZ(Vector3D z) { axisZ = z; };

   /// Set the axis rotation and rotate this Bone
   /// @param a given rotation angles
   /// @param order given order of rotations
   /// @param isDeg true if degree is the angle unit
   void setAxisRot(Vector3D a, string order, bool isDeg);
   
   /// Computes length * direction of Bone
   /// @return length * direction
   Vector3D lenXdir();
   
private:
   string      name; /// Name of this bone (unique)
   Vector3D    direction; /// Direction vector of this bone
   double      length; /// Length of this bone 
   string      axisOrder; /// Transformations order for this bone
   Vector3D    axisX, /// Local coordinate axis x
               axisY, /// Local coordinate axis y
               axisZ; /// Local coordinate axis z   
   Vector3D    rotationAxis; /// Rotation angles of local coordinate axis
   string      rotAxisOrder; /// Order for axis rotation
};

/// Output operator
inline ostream & operator <<(std::ostream &os, Bone *b) {
   os << "[" << b->getName() << "], ";
   os << "[" << b->getDirection() << "], ";
   os << "[" << b->getLength() << "], ";
   os << "[" << b->getAxisOrder() << "], ";
   os << "[" << b->getRotationAxis() << "], ";
   os << "[" << b->getRotAxisOrder() << "]";
   return os;
}

#endif /*BONE_H_*/
